
package de.justphil.tcg.tcgserver.game.mechanics.property.properties;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;

import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.game.mechanics.event.Event;
import de.justphil.tcg.tcgserver.game.mechanics.event.Scheduler;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.monster.Monster;
import de.justphil.tcg.tcgserver.game.mechanics.monster.MonsterList;
import de.justphil.tcg.tcgserver.game.mechanics.property.Property;
import org.slf4j.Logger;
import static de.justphil.tcg.tcgserver.commons.logging.TCGLogging.*;

public class Lazy extends Property {
	
	private static final Logger	log	= gameLogger(Lazy.class);
	private double				remainingTime;
	private Scheduler			scheduler;
	
	/**
	 * Constructor
	 * 
	 * @param game
	 */
	public Lazy(Game game) {
	
		super(game);
		if (game != null) {
			this.scheduler = game.getScheduler();
		}
	}
	
	@Override
	public int getType() {
	
		return PROPERTY_LAZY;
	}
	
	@Override
	protected MonsterList handleEvent(Event event) {
	
		switch (event.getType()) {
			case Event.EVENT_MONSTERS_TURN:
				handleMonstersTurn((Monster) event.getData());
				break;
//			case Event.EVENT_EVENT_SCHEDULED:
//				handleEventScheduled((Event) event.getData());
//				break;
			default:
				assert false;
				break;
		}
		return null;
	}
	
	@Override
	protected List<Integer> getListeningEventTypes() {
	
		List<Integer> types = super.getListeningEventTypes();
		types.add(Event.EVENT_MONSTERS_TURN);
//		types.add(Event.EVENT_EVENT_SCHEDULED);
		return types;
	}
	
	@Override
	protected MonsterList handleActivation() {
	
		Event event = new Event(Event.EVENT_MONSTERS_TURN, getMonster());
		remainingTime = scheduler.getTimeToEvent(event);
		if (remainingTime >= 0) {
			stopMonster();
		}
		else {
			log.debug("Could not stop the monster, because it has not been scheduled yet.",
					new Object[] {});
		}
		return null;
	}
	
	@Override
	protected MonsterList handleDeactivation() {
	
		resumeMonster();
		return null;
	}
	
	private void handleMonstersTurn(Monster monster) {
	
		if (getMonster().equals(monster)) {
			assert false : "This Monster must not have turn!";
			log.error("The Monster ({}) must not have turn!", getMonster());
		}
	}
	
//	private void handleEventScheduled(Event event) {
//	
//		if (event.getType() == Event.EVENT_MONSTERS_TURN && event.getData().equals(getMonster())) {
//			remainingTime = scheduler.getTimeToEvent(event);
//			if (remainingTime == -1) {
//				log.warn("Event ({}) has never been scheduled!", new Object[] {
//					event });
//				assert false;
//			}
//			stopMonster();
//		}
//	}
	
	private void stopMonster() {
	
		log.info("Lazy is stopping Monster ({}).", getMonster());
		scheduler.unschedule(new Event(Event.EVENT_MONSTERS_TURN, getMonster()));
	}
	
	private void resumeMonster() {
	
		log.info("Lazy is resuming a Monster ({}).", getMonster());
		try {
			scheduler.scheduleLast(new Event(Event.EVENT_MONSTERS_TURN, getMonster()),
					remainingTime);
		}
		catch (TCGException e) {
			assert false : e.getMessage();
		}
	}
	
	@Override
	public void writeData(Game game, DataOutput out) throws IOException {
	
		super.writeData(game, out);
		out.writeDouble(remainingTime);
	}
	
	@Override
	public void readData(Game game, DataInput in) throws IOException {
	
		super.readData(game, in);
		remainingTime = in.readDouble();
		scheduler = game.getScheduler();
	}
}
